
#define connection details, etc.
#to the Sribi bot list.
class Bot
     
     @@port = 6667
     @@nick = "SribiBot"
     @@username = "Sribi"
     @@realname = "Sribi - The Simple Ruby IRC Interface"
     @@debug = false
     @@prefix = "!"
     @@pm_commands, @@chan_commands = nil
     
     attr_reader :server
     #Advanced users only! Simply use Sribi.start to do this.
     def initialize
          @names = {}
          @server = Server.new(@@host, @@port)
          puts "Initializing pong response loop..."
          begin_pong_loop
          puts "Initializing server message handling..."
          begin_listen_loop
          puts "Sending user info..."
          @server.send({:command => "NICK", :params => [@@nick]})
          @server.send({:command => "USER", :params => [@@username, @@host, @@host, @@realname]})
          puts "Bot initialized."
          on_connect
          Thread.new{loop {loop_iterate} }
     end
     def self.server(serv, port = 6667)
          @@host = serv
          @@port = port
     end
     def self.nick(nickname)
          @@nick = nickname
     end
     def self.username(user)
          @@username = user
     end
     def self.realname(name)
          @@realname = name
     end
     def self.debug(bool = true)
          @@debug = bool
     end
     def self.prefix(prf)
          @@prefix = prf
     end
     #Possible types - :privmsg, :channel
     def self.commands(value = nil, type = :channel)
          if value and type == :channel
               return @@chan_commands = value.new
          end
          if value and type == :privmsg
               return @@pm_commands = value.new
          end
          #is the type channel?
          if type == :channel
               return @@chan_commands
          end
          #return the private message commands instance
          return @@pm_commands
     end
     
          
     def channel_join(chan)
          puts "Joining #{chan}..."
          @server.send({:command => "JOIN", :params => [chan]})
          puts "Joined #{chan}."
     end
     def private_message(nick, message)
          @server.send({:command => "PRIVMSG", :params => [nick, message]})
          puts "[#{@@nick}] #{message}"
     end
     def private_action(nick, action)
          ctcp_send(nick, "action", action)
          puts "#{@@nick} #{action}"
     end
     def channel_message(chan, message)
          @server.send({:command => "PRIVMSG", :params => [chan, message]})
          puts "<#{@@nick}> #{message}"
     end
     def notice(target, message)
          @server.send({:command => "NOTICE", :params => [target, message]})
          puts "--#{@@nick}-- #{message}"
     end
     def channel_action(chan, action)
          ctcp_send(chan, "action", action)
          puts "#{@@nick} #{action}"
     end
     def ctcp_send(target, type, data = "")
          data = "\001#{type.upcase} #{data}\001"
          @server.send({
               :command => "PRIVMSG",
               :params => [target, data]
          })
     end
     def ctcp_ping(target)
          ctcp_send(target, "ping", Time.now.to_i.to_s)
     end
     def ctcp_clientinfo(target)
          ctcp_send(target, "clientinfo")
     end
     def ctcp_source(target)
          ctcp_send(target, "source")
     end
     def ctcp_time(target)
          ctcp_send(target, "time")
     end
     def self.inherited(bot)
          Sribi.add_bot(bot)
     end
     #Useful for joining channels and sending greeting messages
     def on_connect
          
     end
     def on_error(error)
          p error
          error.backtrace.each do |backtrace|
               puts backtrace
          end
          exit
     end
     def method_missing(method, *args)
          @@chan_commands.send method, *args if @@chan_commands != nil
          @@pm_commands.send method, *args if @@pm_commands != nil
     end
     
     private
     def begin_pong_loop
          Thread.new {
               loop do
                    sleep 30
                    @server.send({:command => "PONG", :params => [@server.ip] })
               end
          }
     end
     def begin_listen_loop
          Thread.new {
               loop do
                    signal = @server.check
                    if signal
                         signal.split("\r\n").each do |line|
                              message = parse_signal(line)
                              Thread.new {
                                   begin
                                        handle message
                                   rescue Object => ex
                                        on_error ex
                                   end
                              }
                         end
                    end
               end
          }
     end
     def handle(message)
          p message if @@debug
          raw_irc_message(message)
          if message[:command] == "PRIVMSG" or message[:command] == "NOTICE"
                    handle_privmsg(message)
          end
          if message[:command] == "MODE"
               handle_mode(message)
          end
          if message[:command] == "353"
               @@chan_commands.channel_names[message[:params][2]] = message[:params][3..message[:params].length]
          end
     end
     def handle_privmsg(message)
          if message[:params][0] == @@nick
               puts "[#{message[:nickname]}] #{message[:params][1]}"
               on_private_message(message[:nickname], message[:params][1])
               if message[:ctcp]
                    case message[:ctcp_type]
                         when "VERSION"
                              if message[:params][1].sub("VERSION", "").length > 1
                                   version_info(message[:nickname], message[:params][1].sub("VERSION ", ""))
                              else
                                   version(message[:nickname])
                              end
                         when "SOURCE"
                              if message[:params][1].sub("SOURCE", "").length > 1
                                   source_info(message[:nickname], message[:params].sub("SOURCE ", ""))
                              else
                                   ctcp_send(message[:nickname], "source", "http://rubyforge.org/frs/download.php/53091/sribi-3.2.6.gem")
                              end
                         when "PING"
                              ctcp_send(message[:nickname], "pong", message[:params][-1].sub("PING ", ""))
                         when "PONG"
                              ctcp_pong(message[:nickname])
                         when "TIME"
                              if message[:params][1].sub("TIME", "").length > 1
                                   time_info(message[:nickname], message[:params].sub("TIME ", ""))
                              else
                                   ctcp_send(message[:nickname], "time", Time.now.to_s)
                              end
                         when "CLIENTINFO"
                              if message[:params][1].sub("CLIENTINFO", "").length > 1
                                   source_info(message[:nickname], message[:params].sub("CLIENTINFO ", ""))
                              else
                                   ctcp_send(message[:nickname], "clientinfo", "SOURCE PING VERSION TIME")
                              end
                    end
                    recv_ctcp(message[:sender], message[:ctcp_type], message[:params][1].sub("VERSION", ""))
               end  
          Thread.new { @@pm_commands.send(message[:params][1].split(" ")[0].sub(@@prefix, "").to_sym, message[:nickname], message[:params][0].split(" ")[1..message[:params][0].length]) } if @@pm_commands and message[:params][1].split(" ")[0] != @@prefix
          else
               puts "<#{message[:nickname]}> #{message[:params][1]}"
               Thread.new {on_channel_message(message[:nickname], message[:params][1], message[:params][0])}
               if message[:params][1] =~ /^#{Regexp.escape(@@prefix)}/ and message[:params][1] != @@prefix
                    Thread.new { @@chan_commands.send(message[:params][1].split(" ")[0].sub(@@prefix, "").to_sym, message[:nickname], message[:params][0], message[:params][1].split(" ")[1..message[:params][1].length]) } if @@chan_commands and message[:params][1].split(" ")[0] != @@prefix
               end
          end
     end
     
     def handle_mode(message)
          modes = message[:params][1].split("")
          type = modes[0]
          modes.delete_at 0
          modes.each do |item|
               index = modes.index item
               mode = modes[index]
               target = message[:params][index + 2]
               setter = message[:sender]
          end
    end
end
